package twi.query;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

import javax.swing.JInternalFrame;
import javax.swing.JPanel;

import twi.sparql.grammer.SparqlList;
import twi.view.ListAttributePanel;
import twi.view.SingleAttributePanel;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

public class QueryTemplate {

	public static ArrayList<QueryTemplate> templateDatabase = new ArrayList<QueryTemplate>();
	private static final File databaseFile = new File(
			"data/db/templates/template.xml");

	ArrayList<String> variableNames = new ArrayList<String>();
	HashMap<String, ArrayList<String>> domainLists = new HashMap<String, ArrayList<String>>();
	ArrayList<SparqlList> lists = new ArrayList<SparqlList>();

	String description = null;
	String name = null;
	String sparql = null;

	public QueryTemplate(ArrayList<String> variableNames,
			HashMap<String, ArrayList<String>> domainLists,
			ArrayList<SparqlList> lists, String description, String name,
			String sparql) {
		super();
		this.variableNames = variableNames;
		this.domainLists = domainLists;
		this.lists = lists;
		this.description = description;
		this.name = name;
		this.sparql = sparql.replace("<", "").replace(">", "");
	}

	public static void loadDatabase() {
		loadDatabase(databaseFile);
	}

	public static void loadDatabase(File file) {
		try {
			XStream xs = new XStream(new DomDriver("ISO-8859-15"));
			FileInputStream fin = new FileInputStream(file);
			templateDatabase = (ArrayList<QueryTemplate>) xs.fromXML(fin);
			fin.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void saveDatabase() {
		saveToXML(databaseFile);
	}

	public static void saveToXML(File file) {
		XStream xs = new XStream(new DomDriver("ISO-8859-15"));
		try {
			if (!file.getParentFile().exists())
				file.getParentFile().mkdirs();
			FileOutputStream fout = new FileOutputStream(file);
			xs.toXML(templateDatabase, fout);
			fout.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void add(QueryTemplate qt) {
		loadDatabase();
		if (qt == null)
			return;
		for (int i = 0; i < templateDatabase.size(); i++)
			if (templateDatabase.get(i).getName().equals(qt.getName()))
				return;
		templateDatabase.add(qt);
		saveDatabase();
	}

	public String getName() {
		return this.name;
	}

	public String getDescription() {
		return this.description;
	}

	public JInternalFrame[] createFrames() {
		JInternalFrame[] out = new JInternalFrame[this.variableNames.size()];
		for (int i = 0; i < out.length; i++)
			out[i] = createFrame(this.variableNames.get(i));
		return out;
	}

	private JInternalFrame createFrame(String varName) {
		if (isInList(varName))
			return createlistFrame(varName);
		else
			return createSingleFrame(varName);
	}

	private JInternalFrame createlistFrame(String varName) {
		ListAttributePanel lap = new ListAttributePanel(varName,
				searchListFor(varName), this.domainLists.get(varName));
		return createFrame(lap, varName);
	}

	private ArrayList<SparqlList> searchListFor(String varName) {
		ArrayList<SparqlList> list = new ArrayList<SparqlList>();
		for (int i = 0; i < this.lists.size(); i++)
			if (this.lists.get(i).containsVariable(varName))
				list.add(lists.get(i));
		return list;
	}

	private JInternalFrame createSingleFrame(String varName) {
		SingleAttributePanel sap = new SingleAttributePanel(varName,
				this.domainLists.get(varName));
		return createFrame(sap, varName);
	}

	private JInternalFrame createFrame(JPanel sap, String varName) {
		JInternalFrame frame = new JInternalFrame();
		frame.add(sap);
		frame.setIconifiable(true);
		frame.setTitle(varName);
		frame.setName(varName + "Frame");
		frame.setVisible(true);
		return frame;
	}

	private boolean isInList(String varName) {
		for (int i = 0; i < this.lists.size(); i++)
			if (this.lists.get(i).containsVariable(varName))
				return true;
		return false;
	}
}
